﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NetBase.Net
{
    public class SqImgLayer : IEnumerable<SqRt>, IDisposable
    {
        protected SqRt[,] layer;

        public int Width { get { return layer.GetLength(0); } }

        public int Height { get { return layer.GetLength(1); } }

        private delegate void XYFunction(XY xy);

        public static IEnumerable<XY> xyGen( int width, int height)
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    XY val;
                    val.X = i; val.Y = j;
                    yield return val;
                }
            }
        }

        public SqImgLayer(Bitmap img) : this( img.Width, img.Height )
        {
            foreach (var xy in xyGen(Width, Height))
            {
                layer[xy.X, xy.Y].setInput(img.GetPixel(xy.X, xy.Y)); 
            }
        }

        public SqImgLayer(int width, int height)
        {
            layer = new SqRt[width, height];
            XYFunction v = (XY xy) => {layer[xy.X, xy.Y] = new SqRt(xy.X, xy.Y);};
            foreach( var item in xyGen(width, height))
            {
                v(item);
            }
            //Parallel.ForEach( xyGen(width, height), item => v(item));
            SetRels();
        }

        public SqRt this[int x, int y]
        {
            get
            {
                if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height))
                {
                    throw new ApplicationException(String.Format("SqImgLayer: Index out of bounds: x={0}, y={1}, Bound=((0,{2}),(0,{3}))", x, y, Width, Height));
                }
                return layer[x,y];
            }
            set
            {
                layer[x,y] = value;
            }
        }

        protected void SetRels()
        {
            XYFunction setRelationForPoint = (XY xy) => 
            {
                if ( (xy.Y + 1) < Height ) 
                    new Rel<SqRt, SqRt>(layer[xy.X, xy.Y], ConTag.UpToMe, layer[xy.X, xy.Y+1], ConTag.AboveToMe);
                if ( (xy.X + 1) < Width ) 
                    new Rel<SqRt, SqRt>(layer[xy.X, xy.Y], ConTag.RightToMe, layer[xy.X+1, xy.Y], ConTag.LeftToMe);
            };
            foreach (var point in xyGen(Width, Height))
            {
                setRelationForPoint(point);
            }
        }



        public void test1()
        {
            Assert.IsNotNull(layer[1, 3], "layer object 1,3 is null");
        }

        public void test2()
        {
            Assert.AreEqual(1, layer[1, 3].X);
        }

        public IEnumerator<SqRt> GetEnumerator()
        {
            return new SqImgLayerEnumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new SqImgLayerEnumerator(this);
        }

        public class SqImgLayerEnumerator : IEnumerator, IEnumerator<SqRt>, IDisposable
        {
            private SqImgLayer sqImgLayer;
            private IEnumerator<XY> iter;

            public SqImgLayerEnumerator(SqImgLayer sqImgLayer)
            {
                this.sqImgLayer = sqImgLayer;
                Reset();
            }

            object IEnumerator.Current
            {
                get
                {
                    return (object)(sqImgLayer[iter.Current.X, iter.Current.Y]);
                }
            }

            SqRt IEnumerator<SqRt>.Current
            {
                get
                {
                    return sqImgLayer[iter.Current.X, iter.Current.Y];
                }
            }

            public bool MoveNext()
            {
                return iter.MoveNext();
            }

            public void Reset()
            {
                iter = xyGen(sqImgLayer.Width, sqImgLayer.Height).GetEnumerator();
            }

            public void Dispose()
            {
                if (sqImgLayer != null)
                {
                    sqImgLayer.Dispose();
                }
            }
        }

        public void Dispose()
        {
            // Do nothing - no disposable resources
        }
    }
}
